#!/usr/bin/env python

'''
Sends sniffed IEEE 802.15.4 packets to Wireshark via a named pipe.

ryan@riverloopsecurity.com
'''

import sys
import signal
import os, tempfile

from killerbee import *

def usage():
    print >>sys.stderr, """
zbwireshark - sends sniffed IEEE 802.15.4 packets to Wireshark via a named pipe

Usage: zbwireshark [-fiwDchp] [-f channel] [-i devnumstring] [-p]
    """

def interrupt(signum, frame):
    global packetcount
    global kb
    global pd
    global pipefname
    global tempdir
    kb.sniffer_off()
    kb.close()
    pd.close()
    os.remove(pipefname)
    os.rmdir(tempdir)
    print "%d packets captured" % packetcount
    sys.exit(0)

pipename = 'zbwireshark'
# Command-line arguments
arg_channel = None
arg_devstring = None
arg_count = -1
arg_ppi = False

# Global
packetcount = 0

while len(sys.argv) > 1:
    op = sys.argv.pop(1)
    if op == '-f':
        arg_channel = int(sys.argv.pop(1))
    elif op == '-i':
        arg_devstring = sys.argv.pop(1)
    elif op == '-h':
        usage()
        sys.exit(0)
    elif op == '-D':
        show_dev()
        sys.exit(0)
    elif op == '-c':
        arg_count = int(sys.argv.pop(1))
    elif op == '-p':
        arg_ppi = True
 
if arg_channel == None:
    print >>sys.stderr, "ERROR: Must specify a channel with -f"
    usage()
    sys.exit(1)
elif arg_channel < 11 or arg_channel > 26:
    print >>sys.stderr, "ERROR: Must specify a valid IEEE 802.15.4 channel between 11 and 26."
    sys.exit(1)
rf_freq_mhz = (arg_channel - 10) * 5 + 2400

# Make FIFO (named pipe)
tempdir = tempfile.mkdtemp()
pipefname = os.path.join(tempdir, pipename)
try:
    os.mkfifo(pipefname) #default mode 0666 (octal)
except OSError, e:
    print "Failed to create FIFO: %s" % e
    sys.exit(-1)

# Start KillerBee
kb = KillerBee(device=arg_devstring)
signal.signal(signal.SIGINT, interrupt)
kb.set_channel(arg_channel)
kb.sniffer_on()

# Start wireshark as soon as KillerBee succeeds
try:
    rc = os.fork()
    if rc == 0:
        os.execlp("wireshark", "/usr/bin/wireshark", "-k", "-i", pipefname)
except OSError, e:
    print "Failed to spawn wireshark: %s" % e
    print "Point Wireshark to read from the pipe file:", pipefname

pd = PcapDumper(DLT_IEEE802_15_4, pipefname, ppi=arg_ppi)

print "zbwireshark: listening on \'%s\', sending to \'%s\'" % (kb.get_dev_info()[0], pipefname)

try:
    while arg_count != packetcount:
        packet = kb.pnext()
        if packet != None:
            packetcount+=1
            pd.pcap_dump(packet['bytes'], ant_dbm=packet['dbm'], freq_mhz=rf_freq_mhz)
except KeyboardInterrupt:
    pass
except IOError as e:
    if e.errno == 32:
        print "ERROR: Pipe broken. Was Wireshark closed or stopped?"

interrupt(0, 0) #shutdown and exit

